#include "stdafx.h"
#include "scoped_ptr.h"
#include "base/file/pe_utils.h"

void FileTimeToLocalSystemTime(const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime)
{
    if(NULL == lpFileTime) {
        return;
    }

    FILETIME oLocalTime = {0};
    ::FileTimeToLocalFileTime(lpFileTime, &oLocalTime);
    ::FileTimeToSystemTime(&oLocalTime, lpSystemTime);
}

CString FormatFileTime(const FILETIME *lpFileTime)
{
    if(NULL == lpFileTime) {
        return _T("");
    }

    unsigned __int64 nTime = ((FILETIMEIntHack *)lpFileTime)->m_nTime;
    CString strOutput;
    strOutput.Format(_T("%I64u:%02I64u:%02I64u.%I64u"),
        nTime / 10000000U / 3600,
        ((nTime / 10000000U) % 3600) / 60,
        (nTime / 10000000U) % 60,
        nTime % 10000000U / 10000);

    return strOutput;
}

bool
GetImageVersion(TCHAR *pImagePath, DWORD *p1stVer, DWORD *p2ndVer, DWORD *p3rdVer, DWORD *p4thVer)
{
    if(NULL == pImagePath) {
        return false;
    }

    if(NULL != p1stVer) *p1stVer = 0;
    if(NULL != p2ndVer) *p2ndVer = 0;
    if(NULL != p3rdVer) *p3rdVer = 0;
    if(NULL != p4thVer) *p4thVer = 0;

    int nVerInfoSize = 0;
    nVerInfoSize = GetFileVersionInfoSize(pImagePath, NULL);
    if(nVerInfoSize == 0) {
        return false;
    }

    VS_FIXEDFILEINFO *pVsInfo;
    unsigned int nFileInfoSize = sizeof(VS_FIXEDFILEINFO);
    char *pBuf = new char[nVerInfoSize];
    if(GetFileVersionInfo(pImagePath, 0, nVerInfoSize, pBuf)) {
        if(VerQueryValue(pBuf, _T("\\"), (void **)&pVsInfo, &nFileInfoSize)) {
            if(NULL != p1stVer) *p1stVer = HIWORD(pVsInfo->dwFileVersionMS);
            if(NULL != p2ndVer) *p2ndVer = LOWORD(pVsInfo->dwFileVersionMS);
            if(NULL != p3rdVer) *p3rdVer = HIWORD(pVsInfo->dwFileVersionLS);
            if(NULL != p4thVer) *p4thVer = LOWORD(pVsInfo->dwFileVersionLS);
        }
    }
    delete pBuf;

    return true;
}

bool
GetImageTime(TCHAR *pImagePath, SYSTEMTIME *pCreateTime, SYSTEMTIME *pModifyTime, SYSTEMTIME *pAccessTime)
{
    if(NULL == pImagePath) {
        return false;
    }

    if(NULL != pCreateTime) memset(pCreateTime, 0, sizeof(SYSTEMTIME));
    if(NULL != pModifyTime) memset(pModifyTime, 0, sizeof(SYSTEMTIME));
    if(NULL != pAccessTime) memset(pAccessTime, 0, sizeof(SYSTEMTIME));

    ScopedHandle hFile(::CreateFile(pImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL));
    if(NULL == hFile) {
        return false;
    }

    FILETIME oCreateTime = {0};
    FILETIME oModifyTime = {0};
    FILETIME oAccessTime = {0};
    ::GetFileTime(hFile, &oCreateTime, &oAccessTime, &oModifyTime);

    if(NULL != pCreateTime) FileTimeToLocalSystemTime(&oCreateTime, pCreateTime);
    if(NULL != pModifyTime) FileTimeToLocalSystemTime(&oModifyTime, pModifyTime);
    if(NULL != pAccessTime) FileTimeToLocalSystemTime(&oAccessTime, pAccessTime);

    return true;
}